home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / win / tclAppInit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  6.0 KB  |  260 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tclAppInit.c --
  3.  *
  4.  *    Provides a default version of the main program and Tcl_AppInit
  5.  *    procedure for Tcl applications (without Tk).  Note that this
  6.  *    program must be built in Win32 console mode to work properly.
  7.  *
  8.  * Copyright (c) 1996 by Sun Microsystems, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * SCCS: @(#) tclAppInit.c 1.12 97/04/30 11:04:50
  14.  */
  15.  
  16. #include "tcl.h"
  17. #include <windows.h>
  18. #include <locale.h>
  19.  
  20. #ifdef TCL_TEST
  21. EXTERN int        Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
  22. EXTERN int        TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
  23. #endif /* TCL_TEST */
  24.  
  25. static void        setargv _ANSI_ARGS_((int *argcPtr, char ***argvPtr));
  26.  
  27.  
  28. /*
  29.  *----------------------------------------------------------------------
  30.  *
  31.  * main --
  32.  *
  33.  *    This is the main program for the application.
  34.  *
  35.  * Results:
  36.  *    None: Tcl_Main never returns here, so this procedure never
  37.  *    returns either.
  38.  *
  39.  * Side effects:
  40.  *    Whatever the application does.
  41.  *
  42.  *----------------------------------------------------------------------
  43.  */
  44.  
  45. int
  46. main(argc, argv)
  47.     int argc;            /* Number of command-line arguments. */
  48.     char **argv;        /* Values of command-line arguments. */
  49. {
  50.     char *p;
  51.     char buffer[MAX_PATH];
  52.  
  53.     /*
  54.      * Set up the default locale to be standard "C" locale so parsing
  55.      * is performed correctly.
  56.      */
  57.  
  58.     setlocale(LC_ALL, "C");
  59.  
  60.     setargv(&argc, &argv);
  61.  
  62.     /*
  63.      * Replace argv[0] with full pathname of executable, and forward
  64.      * slashes substituted for backslashes.
  65.      */
  66.  
  67.     GetModuleFileName(NULL, buffer, sizeof(buffer));
  68.     argv[0] = buffer;
  69.     for (p = buffer; *p != '\0'; p++) {
  70.     if (*p == '\\') {
  71.         *p = '/';
  72.     }
  73.     }
  74.  
  75.     Tcl_Main(argc, argv, Tcl_AppInit);
  76.     return 0;            /* Needed only to prevent compiler warning. */
  77. }
  78.  
  79.  
  80. /*
  81.  *----------------------------------------------------------------------
  82.  *
  83.  * Tcl_AppInit --
  84.  *
  85.  *    This procedure performs application-specific initialization.
  86.  *    Most applications, especially those that incorporate additional
  87.  *    packages, will have their own version of this procedure.
  88.  *
  89.  * Results:
  90.  *    Returns a standard Tcl completion code, and leaves an error
  91.  *    message in interp->result if an error occurs.
  92.  *
  93.  * Side effects:
  94.  *    Depends on the startup script.
  95.  *
  96.  *----------------------------------------------------------------------
  97.  */
  98.  
  99. int
  100. Tcl_AppInit(interp)
  101.     Tcl_Interp *interp;        /* Interpreter for application. */
  102. {
  103.     if (Tcl_Init(interp) == TCL_ERROR) {
  104.     return TCL_ERROR;
  105.     }
  106.  
  107. #ifdef TCL_TEST
  108.     if (Tcltest_Init(interp) == TCL_ERROR) {
  109.     return TCL_ERROR;
  110.     }
  111.     Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init,
  112.             (Tcl_PackageInitProc *) NULL);
  113.     if (TclObjTest_Init(interp) == TCL_ERROR) {
  114.     return TCL_ERROR;
  115.     }
  116. #endif /* TCL_TEST */
  117.  
  118.     /*
  119.      * Call the init procedures for included packages.  Each call should
  120.      * look like this:
  121.      *
  122.      * if (Mod_Init(interp) == TCL_ERROR) {
  123.      *     return TCL_ERROR;
  124.      * }
  125.      *
  126.      * where "Mod" is the name of the module.
  127.      */
  128.  
  129.     /*
  130.      * Call Tcl_CreateCommand for application-specific commands, if
  131.      * they weren't already created by the init procedures called above.
  132.      */
  133.  
  134.     /*
  135.      * Specify a user-specific startup file to invoke if the application
  136.      * is run interactively.  Typically the startup file is "~/.apprc"
  137.      * where "app" is the name of the application.  If this line is deleted
  138.      * then no user-specific startup file will be run under any conditions.
  139.      */
  140.  
  141.     Tcl_SetVar(interp, "tcl_rcFileName", "~/tclshrc.tcl", TCL_GLOBAL_ONLY);
  142.     return TCL_OK;
  143. }
  144.  
  145. /*
  146.  *-------------------------------------------------------------------------
  147.  *
  148.  * setargv --
  149.  *
  150.  *    Parse the Windows command line string into argc/argv.  Done here
  151.  *    because we don't trust the builtin argument parser in crt0.  
  152.  *    Windows applications are responsible for breaking their command
  153.  *    line into arguments.
  154.  *
  155.  *    2N backslashes + quote -> N backslashes + begin quoted string
  156.  *    2N + 1 backslashes + quote -> literal
  157.  *    N backslashes + non-quote -> literal
  158.  *    quote + quote in a quoted string -> single quote
  159.  *    quote + quote not in quoted string -> empty string
  160.  *    quote -> begin quoted string
  161.  *
  162.  * Results:
  163.  *    Fills argcPtr with the number of arguments and argvPtr with the
  164.  *    array of arguments.
  165.  *
  166.  * Side effects:
  167.  *    Memory allocated.
  168.  *
  169.  *--------------------------------------------------------------------------
  170.  */
  171.  
  172. static void
  173. setargv(argcPtr, argvPtr)
  174.     int *argcPtr;        /* Filled with number of argument strings. */
  175.     char ***argvPtr;        /* Filled with argument strings (malloc'd). */
  176. {
  177.     char *cmdLine, *p, *arg, *argSpace;
  178.     char **argv;
  179.     int argc, size, inquote, copy, slashes;
  180.     
  181.     cmdLine = GetCommandLine();
  182.  
  183.     /*
  184.      * Precompute an overly pessimistic guess at the number of arguments
  185.      * in the command line by counting non-space spans.
  186.      */
  187.  
  188.     size = 2;
  189.     for (p = cmdLine; *p != '\0'; p++) {
  190.     if (isspace(*p)) {
  191.         size++;
  192.         while (isspace(*p)) {
  193.         p++;
  194.         }
  195.         if (*p == '\0') {
  196.         break;
  197.         }
  198.     }
  199.     }
  200.     argSpace = (char *) ckalloc((unsigned) (size * sizeof(char *) 
  201.         + strlen(cmdLine) + 1));
  202.     argv = (char **) argSpace;
  203.     argSpace += size * sizeof(char *);
  204.     size--;
  205.  
  206.     p = cmdLine;
  207.     for (argc = 0; argc < size; argc++) {
  208.     argv[argc] = arg = argSpace;
  209.     while (isspace(*p)) {
  210.         p++;
  211.     }
  212.     if (*p == '\0') {
  213.         break;
  214.     }
  215.  
  216.     inquote = 0;
  217.     slashes = 0;
  218.     while (1) {
  219.         copy = 1;
  220.         while (*p == '\\') {
  221.         slashes++;
  222.         p++;
  223.         }
  224.         if (*p == '"') {
  225.         if ((slashes & 1) == 0) {
  226.             copy = 0;
  227.             if ((inquote) && (p[1] == '"')) {
  228.             p++;
  229.             copy = 1;
  230.             } else {
  231.             inquote = !inquote;
  232.             }
  233.                 }
  234.                 slashes >>= 1;
  235.             }
  236.  
  237.             while (slashes) {
  238.         *arg = '\\';
  239.         arg++;
  240.         slashes--;
  241.         }
  242.  
  243.         if ((*p == '\0') || (!inquote && isspace(*p))) {
  244.         break;
  245.         }
  246.         if (copy != 0) {
  247.         *arg = *p;
  248.         arg++;
  249.         }
  250.         p++;
  251.         }
  252.     *arg = '\0';
  253.     argSpace = arg + 1;
  254.     }
  255.     argv[argc] = NULL;
  256.  
  257.     *argcPtr = argc;
  258.     *argvPtr = argv;
  259. }
  260.